﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;

namespace Digitalmes.ControlEx;

public partial class RectCanvas : UserControl, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    /// <summary>
    /// 配置名称
    /// </summary>
    public string? ProfileName { get; private set; }

    /// <summary>
    /// 是否允许用鼠标拖拽 Led 控件
    /// </summary>
    public bool AllowMouseDrop { get; set; }

    /// <summary>
    /// 获取或设置图片目录，默认为 ./Assets/Images/ 目录。
    /// </summary>
    public string ImageBaseDirectory { get; set; } = Path.Combine(AppContext.BaseDirectory, "Assets", "Images");

    public RectCanvas()
    {
        InitializeComponent();
        DataContext = this;
    }

    private double _canvasWidth;
    public double CanvasWidth
    {
        get { return _canvasWidth; }
        set { _canvasWidth = value; OnPropertyChanged(nameof(CanvasWidth)); }
    }

    private double _canvasHeight;
    public double CanvasHeight
    {
        get { return _canvasHeight; }
        set { _canvasHeight = value; OnPropertyChanged(nameof(CanvasHeight)); }
    }

    /// <summary>
    /// 更改配置
    /// </summary>
    /// <param name="profile">配置项</param>
    public void ChangeProfile(RectProfile profile)
    {
        ProfileName = profile.Name;
        CanvasWidth = profile.CanvasWidth;
        CanvasHeight = profile.CanvasHeight;

        var imagePath = Path.Combine(ImageBaseDirectory, profile.ImageName);
        if (Path.Exists(imagePath))
        {
            CanvasImage.Source = new BitmapImage(new Uri(imagePath));
        }

        PointCanvas.Children.Clear(); // 情况点位
        foreach (var point in profile.Points)
        {
            AddRect(point);
        }
    }

    /// <summary>
    /// 更改状态
    /// </summary>
    public void ChangeState(string group, int no)
    {
        var rect = PointCanvas.Children
            .OfType<Rect>()
            .FirstOrDefault(s => s.Group == group && s.No == no);
        if (rect is null)
        {
            return;
        }

        rect.State = rect.State == rect.OriginalState ? RectState.Done : rect.OriginalState;
    }

    /// <summary>
    /// 添加矩形
    /// </summary>
    /// <param name="point"></param>
    public void AddRect(RectPoint point)
    {
        Rect rect = new()
        {
            Width = point.Width,
            Height = point.Height,
            Text = point.Text,
            No = point.No,
            Group = point.Group,
            State = point.State,
            OriginalState = point.State,
        };
        rect.PreviewMouseDown += (sender, e) =>
        {
            var control = (Rect)sender;
            if (AllowMouseDrop && !control.IsPreviewMouseDown)
            {
                control.IsPreviewMouseDown = true;
                control.MouseDownPosition = e.GetPosition(this); // 获取鼠标位置
                control.CaptureMouse();
            }
        };
        rect.PreviewMouseMove += (sender, e) =>
        {
            var control = (Rect)sender;
            if (AllowMouseDrop && control.IsPreviewMouseDown)
            {
                var pos = e.GetPosition(this);
                var dp = pos - control.MouseDownPosition;
                var x = control.CanvasPosition.X + dp.X;
                var y = control.CanvasPosition.Y + dp.Y;

                // 不允许移动超出边界
                if (x < 0 || x > PointCanvas.Width
                    || y < 0 || y > PointCanvas.Height)
                {
                    return;
                }

                Canvas.SetLeft(control, x);
                Canvas.SetTop(control, y);
            }
        };
        rect.PreviewMouseUp += (sender, e) =>
        {
            var control = (Rect)sender;
            if (AllowMouseDrop && control.IsPreviewMouseDown)
            {
                control.IsPreviewMouseDown = false;
                control.ReleaseMouseCapture();

                // 鼠标松开时更新rect当前位置
                control.CanvasPosition = new Point(Canvas.GetLeft(control), Canvas.GetTop(control));
            }
        };

        PointCanvas.Children.Add(rect);
        Canvas.SetLeft(rect, point.X);
        Canvas.SetTop(rect, point.Y);

        // 计算rect当前位置
        rect.CanvasPosition = new Point(Canvas.GetLeft(rect), Canvas.GetTop(rect));
    }

    /// <summary>
    /// 获取 Rect 集合
    /// </summary>
    /// <returns></returns>
    public IReadOnlyList<Rect> GetCollection()
    {
        return PointCanvas.Children
            .OfType<Rect>()
            .ToList();
    }

    protected internal virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
